use std::{sync::mpsc,thread}; //  mpsc : multi procedure, single channel
//use rand::prelude::*;

const NUM_PRODUCERS: usize  = 4;
use anyhow::{anyhow, Ok, Result};
fn main() -> Result<()> {
    let (tx,rx) = mpsc::channel();

      // 创建producers
    for i in 0..NUM_PRODUCERS {
        let tx = tx.clone();
        thread::spawn(move || producer(i,tx));
    }
    drop(tx); // 上面  tx 每次使用都是clone的， 导致本身并没有被用到， 这里就要主动drop掉

    // 其实move 没有也没事
    let consumer = thread::spawn(move || {
        for msg in rx {
            println!("consumer : {:?}", msg);
        }

        println!("consumer exit!");
    });

    // 前面 被 move了 rx ， 所以不能再用了
     // rx.recv();
    // anyhow 没有对  joinHandler 的处理，    为什么可以用anyhow 的error< 因为， 输出的就是anyhow的
    consumer.join()
    .map_err(|e | anyhow!("Thread join error : {:?}",e))?;
// 几个 |  真看不懂

    // 创建consumers

    Ok(())
}

fn producer(idx: usize, tx: mpsc::Sender<Msg>) -> Result<()>{
    loop {
        let value = rand::random::<u32>();
        tx.send(Msg::new(idx, value))?;
        thread::sleep(std::time::Duration::from_millis(1000));

        // random  exit producer
         if rand::random::<u8>() % 10 ==0 {
            println!("producer {}  exit", idx);
            break;
         }
    }

    Ok(())
}

#[derive(Debug)]
struct  Msg{
    idx: usize,
    value: u32,
}


impl Msg{
    fn new(idx: usize, value: u32) -> Self {
        Self{idx, value}
    }
}